"""
图片加载工具模块
用于异步加载网络图片并缓存
"""

import os
import requests
from PyQt5.QtCore import QThread, pyqtSignal, QObject
from PyQt5.QtGui import QPixmap
from PIL import Image
from io import BytesIO
import hashlib


class ImageLoader(QThread):
    """异步图片加载器"""
    
    # 信号：图片加载完成
    image_loaded = pyqtSignal(str, QPixmap)  # (image_url, pixmap)
    # 信号：图片加载失败
    image_failed = pyqtSignal(str, str)      # (image_url, error_message)
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.image_queue = []
        self.cache_dir = "cache/images"
        self.running = False
        
        # 创建缓存目录
        os.makedirs(self.cache_dir, exist_ok=True)
        
        # 请求头
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36'
        }
    
    def load_image(self, image_url: str, target_size: tuple = (200, 150)):
        """
        添加图片到加载队列
        
        Args:
            image_url: 图片URL
            target_size: 目标尺寸 (width, height)
        """
        if image_url and image_url not in [item[0] for item in self.image_queue]:
            self.image_queue.append((image_url, target_size))
            if not self.running:
                self.start()
    
    def run(self):
        """线程运行方法"""
        self.running = True
        
        while self.image_queue and self.running:
            image_url, target_size = self.image_queue.pop(0)
            
            try:
                # 检查缓存
                cache_path = self._get_cache_path(image_url)
                if os.path.exists(cache_path):
                    pixmap = QPixmap(cache_path)
                    if not pixmap.isNull():
                        # 缩放图片
                        scaled_pixmap = pixmap.scaled(
                            target_size[0], target_size[1],
                            aspectRatioMode=1,  # KeepAspectRatio
                            transformMode=1     # SmoothTransformation
                        )
                        self.image_loaded.emit(image_url, scaled_pixmap)
                        continue
                
                # 下载图片
                response = requests.get(image_url, headers=self.headers, timeout=10)
                response.raise_for_status()
                
                # 使用PIL处理图片
                image = Image.open(BytesIO(response.content))
                
                # 转换为RGB模式（如果需要）
                if image.mode != 'RGB':
                    image = image.convert('RGB')
                
                # 调整图片尺寸
                image.thumbnail(target_size, Image.Resampling.LANCZOS)
                
                # 保存到缓存
                image.save(cache_path, 'JPEG', quality=85)
                
                # 转换为QPixmap
                pixmap = QPixmap(cache_path)
                if not pixmap.isNull():
                    self.image_loaded.emit(image_url, pixmap)
                else:
                    self.image_failed.emit(image_url, "图片格式不支持")
                    
            except requests.RequestException as e:
                self.image_failed.emit(image_url, f"网络错误: {str(e)}")
            except Exception as e:
                self.image_failed.emit(image_url, f"处理错误: {str(e)}")
        
        self.running = False
    
    def _get_cache_path(self, image_url: str) -> str:
        """
        获取图片缓存路径
        
        Args:
            image_url: 图片URL
            
        Returns:
            str: 缓存文件路径
        """
        # 使用URL的MD5作为文件名
        url_hash = hashlib.md5(image_url.encode()).hexdigest()
        return os.path.join(self.cache_dir, f"{url_hash}.png")
    
    def clear_cache(self):
        """清空图片缓存"""
        try:
            for filename in os.listdir(self.cache_dir):
                file_path = os.path.join(self.cache_dir, filename)
                if os.path.isfile(file_path):
                    os.remove(file_path)
        except Exception as e:
            print(f"清空缓存失败: {e}")
    
    def stop(self):
        """停止图片加载"""
        self.running = False
        self.image_queue.clear()
        if self.isRunning():
            self.quit()
            self.wait()


class ImageCache:
    """图片缓存管理器"""
    
    def __init__(self, cache_dir: str = "cache/images"):
        self.cache_dir = cache_dir
        self.memory_cache = {}  # 内存缓存
        self.max_memory_cache = 50  # 最大内存缓存数量
        
        # 创建缓存目录
        os.makedirs(self.cache_dir, exist_ok=True)
    
    def get_cached_image(self, image_url: str, target_size: tuple = (200, 150)) -> QPixmap:
        """
        获取缓存的图片
        
        Args:
            image_url: 图片URL
            target_size: 目标尺寸
            
        Returns:
            QPixmap: 图片对象，如果没有缓存则返回空对象
        """
        cache_key = f"{image_url}_{target_size[0]}x{target_size[1]}"
        
        # 检查内存缓存
        if cache_key in self.memory_cache:
            return self.memory_cache[cache_key]
        
        # 检查文件缓存
        cache_path = self._get_cache_path(image_url)
        if os.path.exists(cache_path):
            pixmap = QPixmap(cache_path)
            if not pixmap.isNull():
                # 缩放并添加到内存缓存
                scaled_pixmap = pixmap.scaled(
                    target_size[0], target_size[1],
                    aspectRatioMode=1,  # KeepAspectRatio
                    transformMode=1     # SmoothTransformation
                )
                self._add_to_memory_cache(cache_key, scaled_pixmap)
                return scaled_pixmap
        
        return QPixmap()  # 返回空图片
    
    def _add_to_memory_cache(self, cache_key: str, pixmap: QPixmap):
        """添加图片到内存缓存"""
        if len(self.memory_cache) >= self.max_memory_cache:
            # 移除最旧的缓存项
            oldest_key = next(iter(self.memory_cache))
            del self.memory_cache[oldest_key]
        
        self.memory_cache[cache_key] = pixmap
    
    def _get_cache_path(self, image_url: str) -> str:
        """获取图片缓存路径"""
        url_hash = hashlib.md5(image_url.encode()).hexdigest()
        return os.path.join(self.cache_dir, f"{url_hash}.png")


# 全局图片加载器实例
image_loader = ImageLoader()
image_cache = ImageCache()
